package co.edu.uniquindio.ondas.daos;


import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import co.edu.uniquindio.ondas.daos.criterio.Criterio;
import co.edu.uniquindio.ondas.dtos.InvestigacionDTO;
import co.edu.uniquindio.ondas.dtos.ResumenEvaluacionDTO;
import co.edu.uniquindio.ondas.dtos.ResumenInvestigacionAsesorDTO;
import co.edu.uniquindio.ondas.dtos.ResumenInvestigacionDTO;
import co.edu.uniquindio.ondas.dtos.ResumenInvestigacionGrupoDTO;
import co.edu.uniquindio.ondas.entidades.Actividad;
import co.edu.uniquindio.ondas.entidades.Asesor;
import co.edu.uniquindio.ondas.entidades.Bitacora1Maestro;
import co.edu.uniquindio.ondas.entidades.Bitacora2;
import co.edu.uniquindio.ondas.entidades.Bitacora2Maestro;
import co.edu.uniquindio.ondas.entidades.Bitacora3;
import co.edu.uniquindio.ondas.entidades.Bitacora3Maestro;
import co.edu.uniquindio.ondas.entidades.Bitacora4Maestro;
import co.edu.uniquindio.ondas.entidades.Bitacora5;
import co.edu.uniquindio.ondas.entidades.Estudiante;
import co.edu.uniquindio.ondas.entidades.InformeAvanceTecnico;
import co.edu.uniquindio.ondas.entidades.InformeFinal;
import co.edu.uniquindio.ondas.entidades.Investigacion;
import co.edu.uniquindio.ondas.entidades.Maestro;
import co.edu.uniquindio.ondas.entidades.Segmento;
/**
 * @version 1.0
 * @author Javier
 * 
 * Session Bean implementation class InvestigacionDAO
 * 
 * @param Investigacion hace referencia a la entidad que va hacer manejada por el DAO.
 * @param Long especifica cual es el tipo de dato de la llave primaria de la entidad. 
 */
public class InvestigacionDAO extends DAO<Investigacion, Long> {

	/**
	 *Manejador de la persistencia
	 */
	private EntityManager entityManager;
	/**
	 * Metodo constructor 
	 *@param entityManager
	 */
	public InvestigacionDAO(EntityManager entityManager) {
		super(entityManager);
		this.entityManager=entityManager;
		// TODO Auto-generated constructor stub
	}

	@Override
	protected Class<Investigacion> getEntityClass() {
		// TODO Auto-generated method stub
		return Investigacion.class;
	}
	
	/**
	 * Metodo que permite consultar y obtener una lista de las Investigaciones por Asesor
	 * @param idAsesor
	 * @return Lista de Investigaciones por Asesor
	 */
	@SuppressWarnings("unchecked")
	public List<ResumenInvestigacionAsesorDTO> getinvAsesor(String idAsesor)
	{
		Query query=entityManager.createQuery("SELECT new co.edu.uniquindio.ondas.dtos.ResumenInvestigacionAsesorDTO(investigacion.identificacion, investigacion.grupo.identificacion, investigacion.grupo.nombre, investigacion.grupo.sede.nombre) FROM Investigacion investigacion WHERE investigacion.asesor.identificacion=:parametro");
		query.setParameter("parametro", idAsesor);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite consultar y obtener una Lista de las Investigaciones por Grupo
	 * @param login
	 * @return Lista de investigaciones por Grupo
	 */
	@SuppressWarnings("unchecked")
	public List<ResumenInvestigacionGrupoDTO> getInvestigacionGrupo(String login) {
		Query query=entityManager.createQuery("SELECT new co.edu.uniquindio.ondas.dtos.ResumenInvestigacionGrupoDTO(i.identificacion, i.activo, i.seleccionado, i.bitacora5.identificacion) FROM Investigacion i WHERE i.grupo.login=:parametro");
		query.setParameter("parametro", login);
		
		return query.getResultList();
	}
	
	/**
	 * Este metodo hace una consulta de la cual selecciona las investigaciones a las cuales se les puede asignar un evaluador
	 * @return Lista de Resumen de la Investigacion
	 */
	@SuppressWarnings("unchecked")
	public List<ResumenInvestigacionDTO> getResumenInvestigacion()
	{
		Query query=entityManager.createQuery("SELECT new co.edu.uniquindio.ondas.dtos.ResumenInvestigacionDTO(i.identificacion, i.grupo.identificacion, i.grupo.nombre, i.grupo.sede.institucion.municipio.nombre, i.grupo.sede.nombre, i.lineaTematica.linea, i.lineaTematica.identificacion, i.nombre) FROM Investigacion i WHERE i.seleccionado='0' AND i.calificado='0' AND i.activo='1' AND i.bitacora2 IS NOT NULL AND i.bitacora3 IS NOT NULL AND i.bitacora1Maestro IS NOT NULL AND i.bitacora2Maestro IS NOT NULL AND i.bitacora3Maestro IS NOT NULL AND i.lineaTematica IS NOT NULL AND i.evaluacionProyectos IS NULL");
		
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite consultar y obtiene una lista de evaluaciones hechas por un Evaluador
	 * @param idEvaluador
	 * @return  Lista de Evaluaciones 
	 */
	@SuppressWarnings("unchecked")
	public List<ResumenEvaluacionDTO> obtenerResumenEvaluacion(String idEvaluador)
	{
		Query query=entityManager.createQuery("SELECT new co.edu.uniquindio.ondas.dtos.ResumenEvaluacionDTO(i.evaluacionProyectos.identificacion, i.identificacion, i.grupo.nombre, i.grupo.sede.institucion.municipio.nombre, i.grupo.sede.nombre, i.grupo.identificacion) FROM Investigacion i WHERE i.evaluacionProyectos.evaluador.identificacion=:parametro AND i.calificado='0'");
		query.setParameter("parametro", idEvaluador);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite consultar y obtener una lista de Bitacora2 dada la identificacion de la Investigacion
	 * @param idInvestigacion
	 * @return Lista de Bitacora2
	 */
	@SuppressWarnings("unchecked")
	public List<Bitacora2> getBitacota2Investigacion(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT i.bitacora2 FROM Investigacion i WHERE i.identificacion=:parametro");
		query.setParameter("parametro", idInvestigacion);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite consultar y obtener una lista de Bitacora3 dada la identificacion de la Investigacion
	 * @param idInvestigacion
	 * @return Lista de Bitacora3
	 */
	@SuppressWarnings("unchecked")
	public List<Bitacora3> getBitacota3Investigacion(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT i.bitacora3 FROM Investigacion i WHERE i.identificacion=:parametro");
		query.setParameter("parametro", idInvestigacion);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite consultar y obtener una lista de Bitacora1Maestro dada la identificacion de la Investigacion
	 * @param idInvestigacion
	 * @return lista de Bitacora1Maestro
	 */
	@SuppressWarnings("unchecked")
	public List<Bitacora1Maestro> getBitacota1MaestroInvestigacion(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT i.bitacora1Maestro FROM Investigacion i WHERE i.identificacion=:parametro");
		query.setParameter("parametro", idInvestigacion);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite consultar y obtener una lista de Bitacora2Maestro dado la identificacion de la Investigacion
	 * @param idInvestigacion
	 * @return Lista Bitacora2Maestro
	 */
	@SuppressWarnings("unchecked")
	public List<Bitacora2Maestro> getBitacota2MaestroInvestigacion(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT i.bitacora2Maestro FROM Investigacion i WHERE i.identificacion=:parametro");
		query.setParameter("parametro", idInvestigacion);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite consultar y obtener una lista de Bitacora3Maestro
	 * @param idInvestigacion
	 * @return Lista Bitacora3Maestros
	 */
	@SuppressWarnings("unchecked")
	public List<Bitacora3Maestro> getBitacota3MaestroInvestigacion(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT i.bitacora3Maestro FROM Investigacion i WHERE i.identificacion=:parametro");
		query.setParameter("parametro", idInvestigacion);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite consultar y obtener una lista de Bitacora4Maestro dado la identificacion de la Investigacion
	 * @param idInvestigacion
	 * @return Bitacora4Maestro
	 */
	@SuppressWarnings("unchecked")
	public List<Bitacora4Maestro> getBitacota4MaestroInvestigacion(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT i.bitacora4Maestro FROM Investigacion i WHERE i.identificacion=:parametro");
		query.setParameter("parametro", idInvestigacion);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite consultar y probar una lista de Informe Finales de una Investigacion dada su Iden
	 * @param idInvestigacion
	 * @return Lista de Informe Finales
	 */
	@SuppressWarnings("unchecked")
	public List<InformeFinal> obtenerInformeFinalInvestigacion(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT i.informeFinal FROM Investigacion i WHERE i.identificacion=:parametro");
		query.setParameter("parametro", idInvestigacion);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite consultar y obtener la lista de Informe de Avance Tecnico dado la identificacion de la Investigacion
	 * @param idInvestigacion
	 * @return Lista de Informe de Avance Tecnico
	 */
	@SuppressWarnings("unchecked")
	public List<InformeAvanceTecnico> obtenerInformeAvanceTecnico(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT i.iTecnico FROM Investigacion i WHERE i.identificacion=:parametro");
		query.setParameter("parametro", idInvestigacion);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite consultar y obtener una Bitacora5 dado la Identificacion de la Investigacion
	 * @param idInvestigacion
	 * @return Bitacora5 de la Investigacion
	 */
	public Bitacora5 obtenerBitacora5Investigacion(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT i.bitacora5 FROM Investigacion i WHERE i.identificacion=:parametro");
		query.setParameter("parametro", idInvestigacion);
		
		return (Bitacora5) query.getSingleResult();
	}
	
	/**
	 * Metodo que permite consultar y obtener las actividades de la Investigacion dado la identificacion de la Investigacion
	 * @param idInvestigacion
	 * @return Lista de Actividades
	 */
	@SuppressWarnings("unchecked")
	public List<Actividad> obtenerActividadesInvestigacion(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT actividad From Investigacion i,IN(i.cronograma.actividades) actividad WHERE i.identificacion=:parametro");
		query.setParameter("parametro", idInvestigacion);
		return query.getResultList();
	}
	
	/**
	 * este metodo hace una consulta en la cual se seleccionan los segmentos de la bitacora5 de una investigacion dada
	 * @param idInvestigacion identificacion de la investigacion de la que se desean obtener los segmentos de su bitacora5 o presupuesto
	 * @return List<Segmento> lista de segmentos pertenecientes a la bitacora5 de dicha investigacion.
	 */
	@SuppressWarnings("unchecked")
	public List<Segmento> obtenerSegmentosInvestigacion(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT segmento From Investigacion i,IN(i.bitacora5.segmentos) segmento WHERE i.identificacion=:parametro");
		query.setParameter("parametro", idInvestigacion);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite consultar y obtener una lista de los Estudiantes por grupo dado el id de la investigacion
	 * @param idInvestigacion
	 * @return Lista de Estudiantes por Grupo
	 */
	@SuppressWarnings("unchecked")
	public List<Estudiante> obtenerEstudiantesGrupo(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT estudiante From Investigacion i,IN(i.grupo.estudiantes) estudiante WHERE i.identificacion=:parametro");
		query.setParameter("parametro", idInvestigacion);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite consultar y obtener una Lista de Maestros por Grupo dato la Indentificacion de la Investigacion
	 * @param idInvestigacion
	 * @return Lista de Maestros por Grupo
	 */
	@SuppressWarnings("unchecked")
	public List<Maestro> obtenerMaestrosGrupo(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT maestro From Investigacion i,IN(i.grupo.maestros) maestro WHERE i.identificacion=:parametro");
		query.setParameter("parametro", idInvestigacion);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite consultar y obtener una lista de Asesores  por investigacion dado la identificacion de la Investigacion
	 * @param idInvestigacion
	 * @return Lista de Asesore por Investigacion
	 */
	@SuppressWarnings("unchecked")
	public List<Asesor> obtenerAsesorInvestigacion(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT i.asesor FROM Investigacion i WHERE i.identificacion=:parametro AND i.asesor IS NOT NULL");
		query.setParameter("parametro", idInvestigacion);
		return query.getResultList();
	}
	
//	public List<Asesor> obtenerAsesorInvestigacion(long idAsesor)
//	{
//		Query query=entityManager.createQuery("");
//		query.setParameter("parametro", idAsesor);
//		return query.getResultList();
//	}
	
//	public Investigacion getInvestigacion(long id)
//	{
//		Query query=entityManager.createQuery("SELECT i FROM Investigacion i WHERE i.identificacion=:parametro");
//		query.setParameter("parametro", id);
//		return (Investigacion) query.getSingleResult();
//	}
	
	/**
	 * metodo encargado de hacer una consulta en la base de datos y retornar una lista
	 * con las investigaciones seleccionadas para asignarles un asesor
	 * @return lista de ResumenInvestigacionDTO con los datos mas importantes
	 * 			a la hora de asignar un asesor
	 */
	@SuppressWarnings("unchecked")
	public List<ResumenInvestigacionDTO> obtenerInvestigacionAsignarAsesor()
	{
		Query query=entityManager.createQuery("SELECT new co.edu.uniquindio.ondas.dtos.ResumenInvestigacionDTO(i.identificacion, i.grupo.identificacion, i.grupo.nombre, i.grupo.sede.institucion.municipio.nombre, i.grupo.sede.nombre, i.lineaTematica.linea, i.lineaTematica.identificacion, i.nombre) FROM Investigacion i WHERE i.seleccionado='1' AND i.calificado='1' AND i.activo='1' AND i.asesor IS NULL");
		
		return query.getResultList();
	}
	
	/**
	 * esta metodo hace una consulta donde se seleccionan las identificacion que que tiene a un asesor especifico asignado, ademas que esten activas
	 * @param idAsesor es la identificacion del asesor por medio de la cual se van a seleccionar las investigaciones
	 * @return List<ResumenInvestigacionDTO> es la lista de las investigaciones que cumplen con las especificaciones
	 */
	@SuppressWarnings("unchecked")
	public List<ResumenInvestigacionDTO> obtenerInvestigacionAsesor(String idAsesor)
	{
		Query query=entityManager.createQuery("SELECT new co.edu.uniquindio.ondas.dtos.ResumenInvestigacionDTO(i.identificacion, i.grupo.identificacion, i.grupo.nombre, i.grupo.sede.institucion.municipio.nombre, i.grupo.sede.nombre, i.lineaTematica.linea, i.lineaTematica.identificacion, i.nombre) FROM Investigacion i WHERE i.seleccionado='1' AND i.activo='1' AND i.asesor.identificacion=:parametro");
		query.setParameter("parametro", idAsesor);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permirte obtener una Linea de investigacion dado la identificacion de la Investigacion
	 * @param idInvestigacion
	 * @return nombre de la Linea de la Investigacion
	 */
	public String obtenerLineaInvestigacion(long idInvestigacion)
	{
		Query query=entityManager.createQuery("SELECT i.lineaTematica.linea FROM Investigacion i WHERE i.identificacion=:parametro");
		query.setParameter("parametro", idInvestigacion);
		return (String) query.getSingleResult();
	}
	
	/**
	 * Metodo que permite obtener el total de Paginas por Investigacion dado un tamno de pagina y una lista de criterios
	 * @param tamanoPag
	 * @param criterios
	 * @return numero de Paginas
	 */
	public Long obtenerTotalPaginasInvestigaciones(int tamanoPag, List<Criterio>criterios)
	{
		String sentencia="SELECT COUNT(i) from Investigacion i WHERE i.identificacion >= '0'";
		
		for (Criterio criterio : criterios) {
			switch (criterio.getTipo()) {
			case ACTIVA:
				sentencia+=" AND i.activo= '"+criterio.getArgumento()+"'";
				break;
				
			case SELECCIONADA:
				sentencia+=" AND i.seleccionado= '"+criterio.getArgumento()+"'";
				break;
				
			case MUNICIPIOIN:
				sentencia+=" AND i.grupo.sede.institucion.municipio.nombre= '"+criterio.getArgumento()+"'";
				break;
				
			case ZONAIN:
				sentencia+=" AND i.grupo.sede.institucion.zona.nombre= '"+criterio.getArgumento()+"'";
				break;
				
			case INSTITUCIONIN:
				sentencia+=" AND i.grupo.sede.institucion.nombre= '"+criterio.getArgumento()+"'";
				break;
				
			case SEDEIN:
				sentencia+=" AND i.grupo.sede.nombre= '"+criterio.getArgumento()+"'";
				break;
				
			default:
				break;
			}
		}		
		
		Query query=entityManager.createQuery(sentencia);
		Long total = (Long) query.getSingleResult();
		return total % tamanoPag != 0 ? (total / tamanoPag) + 1 : total / tamanoPag;
	}
	
	/**
	 * Metodo que permite consultar y obtener una Lista de Paginas de Investigacion
	 * @param numPag
	 * @param tamanoPag
	 * @param criterios
	 * @return Lisa de Paginas de Investigacion
	 */
	@SuppressWarnings("unchecked")
	public List<ResumenInvestigacionDTO> obtenerPaginaInvestigacion(int numPag, int tamanoPag, List<Criterio>criterios) {
		String sentencia="SELECT new co.edu.uniquindio.ondas.dtos.ResumenInvestigacionDTO(i.identificacion, i.grupo.identificacion, i.grupo.nombre, i.grupo.sede.institucion.municipio.nombre, i.grupo.sede.nombre, i.lineaTematica.linea, i.lineaTematica.identificacion, i.nombre) FROM Investigacion i WHERE i.identificacion >= '0'";
		
		for (Criterio criterio : criterios) {
			switch (criterio.getTipo()) {
			case ACTIVA:
				sentencia+=" AND i.activo= '"+criterio.getArgumento()+"'";
				break;
				
			case SELECCIONADA:
				sentencia+=" AND i.seleccionado= '"+criterio.getArgumento()+"'";
				break;
				
			case MUNICIPIOIN:
				sentencia+=" AND i.grupo.sede.institucion.municipio.nombre= '"+criterio.getArgumento()+"'";
				break;
				
			case ZONAIN:
				sentencia+=" AND i.grupo.sede.institucion.zona.nombre= '"+criterio.getArgumento()+"'";
				break;
				
			case INSTITUCIONIN:
				sentencia+=" AND i.grupo.sede.institucion.nombre= '"+criterio.getArgumento()+"'";
				break;
				
			case SEDEIN:
				sentencia+=" AND i.grupo.sede.nombre= '"+criterio.getArgumento()+"'";
				break;
				
			default:
				break;
			}
		}		
		
		Query query=entityManager.createQuery(sentencia);
		int primerResultado = (numPag - 1) * tamanoPag;
		query = query.setFirstResult(primerResultado );
		query = query.setMaxResults(tamanoPag);
		return query.getResultList();
	}
	
	/**
	 * Metodo que permite obtener el numero de Investigaciones por sede dado el identificador de la Investigacion
	 * @param idSede
	 * @return Numero de Investigaciones Por Sede
	 */
	public long numeroInvestigacioSede(long idSede)
	{
		Query query=entityManager.createQuery("SELECT COUNT(i) FROM Investigacion i WHERE i.activo='1' AND i.grupo.sede.identificacion=:parametro");
		query.setParameter("parametro", idSede);
		return (Long) query.getSingleResult();
	}
	/**
	 * Metodo que permite consultar y obtener el numero de Invetigacion por sede seleccionadas 
	 * @param idSede
	 * @return
	 */
	public long numeroInvestigacioSelSede(long idSede)
	{
		Query query=entityManager.createQuery("SELECT COUNT(i) FROM Investigacion i WHERE i.activo='1' AND i.seleccionado='1' AND i.grupo.sede.identificacion=:parametro");
		query.setParameter("parametro", idSede);
		return (Long) query.getSingleResult();
	}
	
	/**
	 * Metodo que permite obtener y consultar el numero de Estudiantes por Sede dada el Identificador de la Investigacion
	 * @param idSede
	 * @return Numero de estudiantes por Sede
	 */
	public long obtenerNumeroEstudiantesSede(long idSede)
	{
		Query query=entityManager.createQuery("SELECT COUNT(estudiante) From Investigacion i,IN(i.grupo.estudiantes) estudiante WHERE i.activo='1' AND i.seleccionado='1' AND i.grupo.sede.identificacion=:parametro");
		query.setParameter("parametro", idSede);
		return (Long) query.getSingleResult();
	}
	
	/**
	 * Metodo que permite obtener y consultar el numero de estudiantes  activos por sede   dad el identificador de la investigacion
	 * @param idSede
	 * @return Numero de de estudiantes Activos
	 */
	public long obtenerNumeroEstudiantesActivosSede(long idSede)
	{
		Query query=entityManager.createQuery("SELECT COUNT(estudiante) From Investigacion i,IN(i.grupo.estudiantes) estudiante WHERE i.activo='1' AND i.grupo.sede.identificacion=:parametro");
		query.setParameter("parametro", idSede);
		return (Long) query.getSingleResult();
	}
	
	/**
	 * Metodo que permite obtener un Lista del Historial de Asesor dado el identificador del Asesor
	 * @param idAsesor
	 * @return Lista del Historial del Asesor
	 */
	@SuppressWarnings("unchecked")
	public List<InvestigacionDTO> obtenerInvestigacionesHistorialAsesor(String idAsesor)
	{
		Query query=entityManager.createQuery("SELECT new co.edu.uniquindio.ondas.dtos.InvestigacionDTO(investigacion.identificacion, investigacion.nombre, investigacion.grupo.nombre) FROM Investigacion investigacion WHERE investigacion.asesor.identificacion=:parametro AND investigacion.activo='1' AND investigacion.seleccionado='1'");
		query.setParameter("parametro", idAsesor);
		return query.getResultList();
	}
}
